﻿using CSRedis;
using Lazy.Captcha.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MySystemSetup.IUser;
using MySystemSetup.RBACDomain;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using TodoApp.Dto;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace MySystemSetup.User
{
    public class UserInfoAppService : ApplicationService, IUserInfoAppService
    {

        private readonly IRepository<UserInfo, string> _userRepository;
        private readonly IRepository<UserRole, int> _userRoleRepository;
        private readonly IRepository<RolePermission, int>  _rolePermissionRepository;

        private readonly IRepository<RoleInfo, int> _roleRepository;
        private readonly ICaptcha _captcha;
        private readonly CSRedisClient Redis;
        public UserInfoAppService(IRepository<UserInfo, string> userRepository, ICaptcha captcha, IRepository<UserRole, int> userRoleRepository, IRepository<RolePermission, int> rolePermissionRepository, IRepository<RoleInfo, int> roleRepository)
        {
            _userRepository = userRepository;
            _captcha = captcha;
            Redis = new CSRedisClient("120.46.54.169:6380");
            _userRoleRepository = userRoleRepository;
            _rolePermissionRepository = rolePermissionRepository;
            _roleRepository = roleRepository;
        }
        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="userDto">要添加的实体</param>
        /// <returns>统一返回格式</returns>
        public async Task<SzrApiResult<UserDto>> AddAsync(UserDto userDto)
        {



            var res = ObjectMapper.Map<UserDto, UserInfo>(userDto);
            await _userRepository.InsertAsync(res);


            return new SzrApiResult<UserDto>()
            {

                code = 200,
                data = userDto,
                msg = "添加成功"
            };
        }

        /// <summary>
        /// 删除的用户
        /// </summary>
        /// <param name="id">要删除的编号</param>
        /// <returns>统一返回格式</returns>
        public async Task DeleteAsync(string id)
        {

            await _userRepository.DeleteAsync(id);

        }

        public async Task<SzrApiPageResult<UserDto>> PageGetList(int page, int limit, string? quNumber)
        {





            var res = await _userRepository.GetQueryableAsync();


            if (quNumber != null)
            {
                res = res.Where(x => x.UserName.Contains(quNumber)).Skip((page - 1) * limit).Take(limit).AsQueryable();


            }
            else
            {
                res = res.Skip((page - 1) * limit).Take(limit).AsQueryable();
            }





            return new SzrApiPageResult<UserDto>()
            {

                code = 200,
                data = ObjectMapper.Map<IQueryable<UserInfo>, List<UserDto>>(res),
                page = (int)Math.Ceiling(res.Count() * 1.0 / limit),
                count = res.Count(),

            };
        }



        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="dto">登录信息</param>
        /// <returns>统一返回格式</returns>
        public async Task<SzrApiResult<UserLogDto>> UserLog(UserLogDto dto)
        {

            var data = Redis.Get("UserCodeId");
            if (data.ToLower() != dto.Captcha.ToLower())
            {


                return new SzrApiResult<UserLogDto>()
                {
                    msg = "验证码错误",
                    code = 414,
                };

            }



            var res = await _userRepository.GetListAsync(c => c.UName == dto.UName);



            if (res.Count == 0)
            {

                return new SzrApiResult<UserLogDto>()
                {
                    code = 400,
                    msg = "用户名不存在"
                };

            }



            if (res.FirstOrDefault().DeleteStatu)
            {
                return new SzrApiResult<UserLogDto>()
                {
                    msg = "该账号已经注销",
                    code = 445,
                };
            }
        ;
            //密码md5加密
            MD5 mD5 = MD5.Create();
            byte[] bytes = mD5.ComputeHash(Encoding.UTF8.GetBytes(dto.UPwd));
            dto.UPwd = BitConverter.ToString(bytes).Replace("-", "");


            if (dto.UPwd != res.FirstOrDefault().UPwd)
            {
                return new SzrApiResult<UserLogDto>()
                {
                    code = 405,
                    msg = "密码错误"
                };

            }
            else
            {

                return new SzrApiResult<UserLogDto>()
                {
                    code = 200,
                    msg = "登录成功",
                    name = res.FirstOrDefault().UName,
                    uId = res.FirstOrDefault().Id,
                    userPhone = res.FirstOrDefault().UserPhone

                };
            }


        }




        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// 

        public async Task<FileStreamResult> GetCaptcha(string id)
        {
            //Redis.Del("UserCodeId");
            var info = _captcha.Generate(id);
            Redis.Set("UserCodeId", info.Code);
            var stream = new MemoryStream(info.Bytes);

            //using(FileStream fs =new FileStream(in))


            return new FileStreamResult(stream, "image/gif");


        }





        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="id">用户编号</param>
        /// <returns>同意返回格式</returns>
        public async Task<SzrApiResult<UserShowDto>> GetUserInfo(string id)
        {




            var info = await _userRepository.GetListAsync();


            var res = info.Where(c => c.Id == id).FirstOrDefault();


            return new SzrApiResult<UserShowDto>()
            {
                code = 200,
                data = res
            };
        }



        /// <summary>
        /// 修改用户名
        /// </summary>
        /// <param name="dto">修改需要的信息</param>
        /// <returns>统一返回格式</returns>
        public async Task<SzrApiResult<UserLogDto>> UpdateUserName(UserLogDto dto)
        {


            var res = await _userRepository.FindAsync(c => c.Id == dto.Id);

            if (res.UpdateLimit == 1)
            {

                return new SzrApiResult<UserLogDto>() { code = 400, msg = "用户名只能修改一次" };
            }

            res.UName = dto.UName;
            res.UpdateLimit += 1;
            await _userRepository.UpdateAsync(res);


            return new SzrApiResult<UserLogDto>() { code = 200, msg = "修改成功" };

        }


        /// <summary>
        /// 修改用户密码
        /// </summary>
        /// <param name="dto">用户Dto</param>
        /// <returns>统一返回格式</returns>
        public async Task<SzrApiResult<UpdatePwdDto>> UpdateUserPwd(UpdatePwdDto dto)
        {




            var info = await _userRepository.GetListAsync();


            var res = info.Where(c => c.Id == dto.Id).FirstOrDefault();

            //密码md5加密
            MD5 mD5 = MD5.Create();
            byte[] bytes = mD5.ComputeHash(Encoding.UTF8.GetBytes(dto.UserPwd));
            dto.UserPwd = BitConverter.ToString(bytes).Replace("-", "");

            if (dto.UserPwd != res.UPwd)
            {

                return new SzrApiResult<UpdatePwdDto>()
                {
                    code = 400,
                    msg = "输入密码有误"
                };
            }
            //密码md5加密

            byte[] newBytes = mD5.ComputeHash(Encoding.UTF8.GetBytes(dto.NewPwd));
            dto.NewPwd = BitConverter.ToString(newBytes).Replace("-", "");


            if (dto.NewPwd == res.UPwd)
            {

                return new SzrApiResult<UpdatePwdDto>()
                {
                    code = 400,
                    msg = "新密码不能与原密码相同"
                };
            }
            res.UPwd = dto.NewPwd;

            await _userRepository.UpdateAsync(res);
            return new SzrApiResult<UpdatePwdDto>()
            {
                code = 200,
                msg = "修改成功"
            };
        }






        /// <summary>
        /// 获取到手机号验证登录码
        /// </summary>
        /// <param name="uTel"></param>
        /// <returns></returns>
        public async Task< SzrApiResult<UserShowDto>> GetTelLogin(string? uTel)
        {

            //传入的手机号进行验证
            SzrApiResult<UserShowDto> apiReturn = new SzrApiResult<UserShowDto>();


            //获取redis中的数据
            var getsecond = await Redis.GetAsync(uTel);
            if (getsecond != null)
            {
                apiReturn.code = 500;
                apiReturn.msg = "请稍后重试";
            }
            else
            {
                //验证通过，生成验证码存入Redis中
                var numert = "1234567890";
                var ges = "";
                for (int i = 0; i < 4; i++)
                {
                    Random random = new Random();

                    // 生成一个介于 0 到 100 之间的随机整数
                    int randomNumber = random.Next(0, numert.Length);
                    ges += numert[randomNumber];
                }


                bool isSuccess=AliInfor.SendMobileMessageByAli(uTel, "羊村管理系统","SMS_465635094",ges);


                if (isSuccess)
                {

                    apiReturn.code = 200;
                    apiReturn.msg = "成功";
                    //存入Redis中
                    await Redis.SetAsync(uTel, ges, TimeSpan.FromMinutes(1000));

                }
                else
                {
                    apiReturn.code = 400;
                    apiReturn.msg = "失败";

                }
                  
              
            }


            return apiReturn;
        }


     
        /// <summary>
        /// 验证机号
        /// </summary>
        /// <param name="uTel">手机号</param>
        /// <param name="code">验证码</param>
        /// <returns></returns>
        public async Task<SzrApiResult<UserShowDto>> UpdateTelInforLogin(string? uTel, string? code, string id)
        {
            SzrApiResult<UserShowDto> apiReturn = new SzrApiResult<UserShowDto>();

            //获取Redis
            //获取redis中的数据
            var getsecond =await Redis.GetAsync(uTel);
            if (getsecond == null)
            {
                apiReturn.code = 500;
                apiReturn.msg = "验证码失效，请重新点击";
            }
            else
            {
                if (getsecond != code)
                {
                    apiReturn.code = 500;
                    apiReturn.msg = "验证码错误，请重新输入";
                }
                else
                {

                    apiReturn.code = 200;
                  

                }
            }

            return apiReturn;
        }

        /// <summary>
        /// 修改手机号
        /// </summary>
        /// <param name="uTel">手机号</param>
        /// <param name="code">验证码</param>
        /// <returns></returns>
        public async Task<SzrApiResult<UserShowDto>> UpdateNewPhone(string? uTel, string? code, string id)
        {
            SzrApiResult<UserShowDto> apiReturn = new SzrApiResult<UserShowDto>();

            //获取Redis
            //获取redis中的数据
            var getsecond = await Redis.GetAsync(uTel);
            if (getsecond == null)
            {
                apiReturn.code = 500;
                apiReturn.msg = "验证码失效，请重新点击";
            }
            else
            {
                if (getsecond != code)
                {
                    apiReturn.code = 500;
                    apiReturn.msg = "验证码错误，请重新输入";
                }
                else
                {

                    apiReturn.code = 200;


                    var res = await _userRepository.FindAsync(c => c.Id == id);

                    res.UserPhone = uTel;

                    await _userRepository.UpdateAsync(res);

                    apiReturn.msg = "修改成功";
                }
            }

            return apiReturn;
        }



        /// <summary>
        /// 注销账号
        /// </summary>
        /// <param name="uTel">手机号</param>
        /// <param name="code">验证码</param>
        /// <returns>统一返回格式</returns>
        public async Task<SzrApiResult<UserShowDto>> UpdateUserSate( string id,string pwd)
        {


            var res = await _userRepository.FindAsync(c => c.Id == id);

            //密码md5加密
            MD5 mD5 = MD5.Create();
            byte[] bytes = mD5.ComputeHash(Encoding.UTF8.GetBytes(pwd));
            pwd = BitConverter.ToString(bytes).Replace("-", "");

            if (pwd != res.UPwd)
            {

                return new SzrApiResult<UserShowDto>()
                {
                    code = 400,
                    msg = "输入密码有误"
                };
            }
            res.DeleteStatu = true;

            await _userRepository.UpdateAsync(res);


            return new SzrApiResult<UserShowDto>()
            {
                code = 200,
                msg = "注销成功"
            };
        }



        /// <summary>
        /// 添加用户信息
        /// </summary>
        /// <param name="dto">要添加的实体</param>
        /// <returns>统一返回格式</returns>
        [UnitOfWork]
        public async Task<SzrApiResult<UserShowDto>> AddUserinfo(AddUserInfoDto dto)
        {




            var unit=await _userRepository.GetListAsync(c => c.UName == dto.UName );


            if (unit.FirstOrDefault() != null )
            {

                return new SzrApiResult<UserShowDto>()
                {
                    code = 400,
                    msg = "用户名已存在"
                };
            }








            dto.Id = Guid.NewGuid().ToString().Replace("-", "");


            var res = ObjectMapper.Map<AddUserInfoDto, UserInfo>(dto);


           
            MD5 mD5 = MD5.Create();
            byte[] newBytes = mD5.ComputeHash(Encoding.UTF8.GetBytes(res.UPwd));
            res.UPwd = BitConverter.ToString(newBytes).Replace("-", "");

            //默认密码为123456

            res.PaymentCode = "123456";

            //添加角色
            await _userRoleRepository.InsertAsync(new UserRole
            {
                UId = dto.Id,
                RoleId = dto.RoleId
            });

            await _userRepository.InsertAsync(res);

            return    new SzrApiResult<UserShowDto>()
            {

                code = 200,
              
                msg = "添加成功"
            };

           

        }



        /// <summary>
        /// 分页显示用户列表
        /// </summary>
        /// <param name="userName">用户姓名</param>
        /// <param name="dId">用户部门</param>
        /// <param name="statu">用户状态</param>
        /// <param name="page">当前页</param>
        /// <param name="limit">页容量</param>
        /// <param name="uId">用户编号</param>
        /// <returns>统一返回格式</returns>
        public async Task<SzrApiPageResult<UserShowDto>> GetUserInfoPageShowAsync(string? userName,int dId,int  statu,int page,int limit,string uId)
        
        
        
        
        
        {

            var list = await _userRepository.GetListAsync();


            list= list.WhereIf(userName != null, c => c.UserName.Contains(userName)).ToList();
            list= list.WhereIf(dId != 0, c => c.DeperId == dId).ToList();
            list= list.WhereIf(statu != 0, c => c.UserState == statu).ToList();


            var userRole = await _userRoleRepository.GetListAsync(c=>c.UId==uId);
            var rolePer = await _rolePermissionRepository.GetListAsync(c=>c.PermissId== "A34");

            return new SzrApiPageResult<UserShowDto>()
            {
                code = 0,
                data = list.Select(c=>new UserShowDto
                {
                    Id = c.Id,
                    UName = c.UName,
                    UserName = c.UserName,
                    UserPhone= c.UserPhone,
                    UserState = c.UserState,
                    ButtonPermiss= userRole.Join(rolePer,c=>c.RoleId,c=>c.RoleId,(c,c1)=>c1)
                    .Select(c=>c.ButtonPermiss).FirstOrDefault(),
                }).Skip((page - 1) * limit).Take(limit).ToList(),
                count = list.Count(),
                page = (int)Math.Ceiling(list.Count() * 1.0 / limit)
            };
        }





          /// <summary>
          /// 删除用户
          /// </summary>
          /// <param name="uId">登录用户编号</param>
          /// <param name="delUId">要删除的用户编号</param>
          /// <returns>统一返回格式</returns>
        [UnitOfWork]
        public async Task<SzrApiResult<UserShowDto>> DeleteShowAsync(string uId, string? delUId)
        {



            //工作单元
            using (var unitOfWork = UnitOfWorkManager.Begin())
            {


                try
                {

                    //用户下的角色列表
                    var userRoleList = await _userRoleRepository.GetListAsync(c => c.UId == uId);

                    //要删除用户下的角色列表
                    var delUserRoleList = await _userRoleRepository.GetListAsync(c => c.UId == delUId);

                    //用户下的角色列表
                    var roleList = await _roleRepository.GetListAsync();

                    if (delUserRoleList.Count!=0)
                    {



                        //查到当当前用户下的最高等级角色
                        var query = roleList.Join(userRoleList, c => c.Id, c => c.RoleId,
                     (c, c1) => c).OrderBy(c => c.RoleGrade).First();


                        var delQuery = roleList.Join(delUserRoleList, c => c.Id, c => c.RoleId,
                           (c, c1) => c).OrderBy(c => c.RoleGrade).First();




                        //查到当当前用户下的最高等级角色

                        if (delQuery.RoleGrade <= query.RoleGrade)
                        {

                            return new SzrApiResult<UserShowDto>()
                            {

                                code = 400,
                                msg = "删除用户角色等级大于等于当前用户角色等级，无法删除",


                            };

                        }

                    }

                        var res = await _userRepository.FindAsync(c => c.Id == delUId);




                        await _userRepository.DeleteAsync(res);


                        //var userRoleList = await _userRoleRepository.GetListAsync(c => c.UId == res.Id);


                        //删除用户角色
                        if (delUserRoleList != null)
                        {
                            foreach (var item in delUserRoleList)
                            {


                                await _userRoleRepository.DeleteAsync(item.Id);
                            }

                        }




                        //提交
                        await unitOfWork.CompleteAsync();
                        return new SzrApiResult<UserShowDto>()
                        {

                            code = 200,
                            msg = "删除成功",


                        };

                    

               


                }
                catch (Exception)
                {
                    // 如果发生异常，则回滚事务
                    unitOfWork.Dispose();

                    throw;
                }

            }
        }




        /// <summary>
        /// 图片上传
        /// </summary>
        /// <param name="file">文件</param>
        /// <returns>返回格式</returns>

        public SzrApiResult<string> UploadImg(IFormFile file)
        {


            string postFile = Directory.GetCurrentDirectory() + @"\wwwroot\Pic\" + file.FileName;

            using (FileStream fs = new FileStream(postFile, FileMode.Create))
            {


                file.CopyTo(fs);
            }



            return new SzrApiResult<string>()
            {


                code = 200,
                data = file.FileName,
                msg = "上传成功"

            };
        }

    }
}
